package ru.averta.notes.other;

import org.apache.lucene.index.IndexReader;
import org.hibernate.SessionFactory;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.SearchFactory;
import org.hibernate.search.reader.ReaderProvider;
import org.hibernate.search.store.DirectoryProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.averta.notes.domain.Site;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * <code>UtilsLucene</code>
 *
 * @author: fedor.belov (fedor.belov@mail.ru)
 * Date: 08.06.11 0:13
 */

@Service
public class UtilsLucene {

    //страница 141 (102) Lucene in Action
    private static final Character[] ESCAPE_CHARS = {'\\', '+', '-', '!', '(',  ')',  ':',  '^', ']', '{', '}', '~', '*', '?'};
    private Set<Character> escapeChars;

    public static final String FIELD_TITLE = "title";
    public static final String FIELD_MARK_CONTENT = "marks.content";
    public static final String FIELD_MARK_COMMENT = "marks.comment";
    public static final String FIELD_FULL_SEARCH_CONTENT = "siteContent.fullSearchContent";
    public static final String FIELD_IMPORTANT_SEARCH_CONTENT = "siteContent.importantSearchContent";

    @Autowired
    private SessionFactory sessionFactory;

    @PostConstruct
    private void setUp() {
        escapeChars = new HashSet<Character>(ESCAPE_CHARS.length);
        escapeChars.addAll(Arrays.asList(ESCAPE_CHARS));
    }

    /**
     * Удаляет (эскейпит) из request запрещенные в lucene символы
     * Заменяет ё на е
     *
     * @param request
     * @return
     */
    public String escapeUserRequest(String request) {
        if (request == null || "".equals(request)) return "";

        StringBuilder source = new StringBuilder(request);
        StringBuilder result = new StringBuilder();

        for (int i=0; i< source.length(); i++) {
            char ch = source.charAt(i);

            if (escapeChars.contains(ch)) {
                result.append("\\");
                result.append(ch);
            } else if (ch == 'ё') {
                result.append('е');
            } else if (ch == 'Ё') {
                result.append('Е');
            } else {
                result.append(ch);
            }
        }

        return result.toString();
    }

    public FullTextSession getFullTextSession() {
        return Search.getFullTextSession(sessionFactory.getCurrentSession());
    }

    /**
     * На основании кода из https://forum.hibernate.org/viewtopic.php?f=9&t=982678&p=2424927&hilit=highlighter#p2424927
     *
     * @return
     */
    public IndexReader getSiteIndexReader() {
        SearchFactory searchFactory = getFullTextSession().getSearchFactory();
        ReaderProvider readerProvider = searchFactory.getReaderProvider();
        DirectoryProvider directoryProvider = searchFactory.getDirectoryProviders(Site.class)[0];
        return readerProvider.openReader(directoryProvider);
    }

    public void closeReader(IndexReader reader) {
        getFullTextSession().getSearchFactory().getReaderProvider().closeReader(reader);
    }
}
